Skip to content
This repository was archived by the owner on Mar 30, 2026. It is now read-only.

Switch NLSolve to BracketingNonlinearSolve for stability detection#180

Merged
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:switch-to-bracketing-nonlinear-solve
Mar 23, 2026
Merged

Switch NLSolve to BracketingNonlinearSolve for stability detection#180
ChrisRackauckas merged 1 commit intoSciML:masterfrom
ChrisRackauckas-Claude:switch-to-bracketing-nonlinear-solve

Conversation

@ChrisRackauckas-Claude
Copy link
Copy Markdown
Contributor

Summary

  • Replaced NLsolve dependency with BracketingNonlinearSolve for stability region boundary detection
  • Uses Bisection() solver with IntervalNonlinearProblem — since stability functions are 1D with |r(0)|=1 (0-stable) and |r(±∞)|>1 (not ∞-stable), bracketing reliably finds the boundary
  • For A-stable methods (e.g. ImplicitEuler) where the entire negative real axis is stable, falls back to a bracket spanning 0

Closes #179

Changes

  • Project.toml: NLsolveBracketingNonlinearSolve in [deps] and [compat]
  • src/DiffEqDevTools.jl: Updated imports
  • src/tableau_info.jl: Rewrote stability_region and imaginary_stability_interval to use IntervalNonlinearProblem{false} with Bisection()

Test plan

  • All existing stability_region_test.jl tests pass (including @inferred type stability checks, Float32 support)
  • Full Pkg.test() passes

🤖 Generated with Claude Code

Replace NLsolve with BracketingNonlinearSolve (Bisection) for finding
stability region boundaries. Since stability functions are 1D with
|r(0)|=1 (0-stable) and |r(±∞)|>1 (not ∞-stable), bracketing between
a point near 0 and a far point reliably finds the boundary. For A-stable
methods, falls back to a bracket spanning 0.

Closes SciML#179

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ChrisRackauckas ChrisRackauckas merged commit 4ed546b into SciML:master Mar 23, 2026
2 of 6 checks passed
# far from 0 (outside stability region). Solvers are 0-stable (|r(0)|=1)
# and not ∞-stable, so a sign change must exist between these points.
near_zero = sign(initial_guess) * one(T) / T(10)
far = initial_guess * T(10)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is 10 big enough to actually find a root?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only method that this doesn't work on is Chebyshev methods, which would fail for other reasons because of its adaptivity of building its tableau. So it's good enough, we can make this open ended another way in the future if someone actually cares, but as a dev tool, good enough.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switch NLSolve to BracketingNonlinearSolve

3 participants